package com.hb.trade.api.routine.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aliyun.oss.model.CannedAccessControlList;
import com.hb.core.pojo.Attachment;
import com.hb.core.pojo.Attachments;
import com.hb.core.pojo.center.sys.entity.FileRecord;
import com.hb.core.pojo.enums.DeployStatusEnum;
import com.hb.core.pojo.project.file.dto.BidFileInfoDTO;
import com.hb.core.pojo.project.opening.entity.BidOpeningSchedule;
import com.hb.core.pojo.project.proj.entity.AbstractProject;
import com.hb.core.pojo.project.section.dto.BidSectionDTO;
import com.hb.core.pojo.project.section.entity.BidSection;
import com.hb.trade.api.routine.util.TradeFileUtil;
import com.hb.trade.client.center.FileClient;
import com.hb.trade.client.project.BidFileInfoClient;
import com.hb.trade.client.project.BidOpeningClient;
import com.hb.trade.client.project.ProjectClient;
import com.hb.trade.client.project.SectionClient;
import lombok.extern.slf4j.Slf4j;
import org.fzzn.core.cache.inmemory.InMemoryService;
import org.fzzn.core.file.entity.HbFileInfo;
import org.fzzn.core.file.entity.HbMultipartFile;
import org.fzzn.core.file.entity.UploadEntity;
import org.fzzn.core.file.service.PersistenceService;
import org.fzzn.core.model.enums.MsgEnum;
import org.fzzn.core.model.msg.Message;
import org.fzzn.core.service.ZipFileService;
import org.fzzn.core.util.Enums;
import org.fzzn.core.util.MsgUtil;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * 招标文件业务处理服务
 *
 * @author zhaojk
 */
@Service
@Slf4j
public class BidFileInfoService {

    /**
     * bidding.pdf - 未签章的招标文件
     */
    public final static String BIDDING = "bidding.pdf";

    /**
     * biddingSignature.pdf - 签过章的招标文件
     */
    public final static String BIDDING_SIGNATURE = "biddingSignature.pdf";

    protected final SectionClient sectionClient;
    protected final BidFileInfoClient bidFileInfoClient;
    protected final BidOpeningClient bidOpeningClient;
    protected final ProjectClient projectClient;
    protected final FileClient fileClient;
    protected final InMemoryService memoryService;
    protected final PersistenceService persistenceService;

    public BidFileInfoService(SectionClient sectionClient,
                              BidFileInfoClient bidFileInfoClient,
                              BidOpeningClient bidOpeningClient,
                              ProjectClient projectClient,
                              FileClient fileClient,
                              InMemoryService memoryService,
                              PersistenceService persistenceService) {
        this.sectionClient = sectionClient;
        this.bidFileInfoClient = bidFileInfoClient;
        this.bidOpeningClient = bidOpeningClient;
        this.projectClient = projectClient;
        this.fileClient = fileClient;
        this.memoryService = memoryService;
        this.persistenceService = persistenceService;
    }

    /**
     * 生成物理招标文件, 文件保存在服务器硬盘上, 文件地址存至内存
     * 文件地址保存内存时间为三分钟内有效
     * <p>
     * 项目中所有签过章的文件命名跟Signature后缀
     * <p>
     * bidding.pdf - 未签章的招标文件
     * biddingSignature.pdf - 签过章的招标文件
     *
     * @return 保存的临时文件ID
     */
    public Message<Long> generateFile(BidSectionDTO sectionDTO) throws IOException {
        Long sectionId = sectionDTO.getSectionId();
        if (sectionId == null) {
            return MsgUtil.msg(MsgEnum.INCORRECT_PARAM);
        }

        // 如果文件之前下载过这里直接返回
        Message<FileRecord> fileMessage = fileClient.getFile("trade_bid_section", sectionId);
        if (fileMessage.isSuccess()) {
            Long id = fileMessage.getData().getId();
            return MsgUtil.success(id);
        }

        // 没有下载过招标文件, 开始生成
        Message<BidSection> info = sectionClient.info(sectionDTO); // 查询标段信息
        if (info.isFail()) {
            log.warn(info.getMessage());
            return MsgUtil.fail(info.getMessage());
        }

        // 招标文件ID
        Long fileId = info.getData().getFileId();
        ZipFileService zipService = ZipFileService.getInstance();

        // 招标文件主体
        Message<BidFileInfoDTO> fileInfo = bidFileInfoClient.getBidFileInfo(fileId);

        BidFileInfoDTO data = fileInfo.getData();

        if(data == null){
            return MsgUtil.fail("招标文件当前尚未发布");
        }

        // 判断招标文件发布状态
        Integer releaseFlag = data.getReleaseFlag();
        if (!Enums.equals(DeployStatusEnum.DEPLOYED, releaseFlag)) {
            return MsgUtil.fail("招标文件当前尚未发布");
        }

        // 未签章的PDF文件
        Attachments pdf = data.getBiddingDocumentPdf();
        if (CollUtil.isNotEmpty(pdf)) {
            File file = TradeFileUtil.parseFile(pdf);
            if (file != null) {
                zipService.add(BIDDING, file);
            }
        }

        // 已签章的PDF文件
        Attachments pdfSign = data.getBiddingDocumentSignaturePdf();
        if (CollUtil.isNotEmpty(pdfSign)) {
            File file = TradeFileUtil.parseFile(pdfSign);
            if (file != null) {
                zipService.add(BIDDING_SIGNATURE, file);
            }
        }

        // 工程量清单及图纸
        Attachments drawing = data.getDrawing();
        if (CollUtil.isNotEmpty(drawing)) {
            for (Attachment attachment : drawing) {
                String realName = Attachments.DRAWING_PREFIX + attachment.getRawFileName() + '.' + attachment.getExtName();
                byte[] bytes = attachment.getThisBytes();
                zipService.add(realName, bytes);
            }
        }

        // 查询评审项
/*        List<ReviewPointItems2Dto> items2Dtos = pointItems2Service.listByFileId(fileId);
        if (CollUtil.isNotEmpty(items2Dtos)) {
            File reviewPoint = new File("temps/reviewPoint.json");
            JSONArray obj = JSONUtil.parseArray(items2Dtos, JSONConfig.create().setIgnoreNullValue(true));
            FileUtil.writeUtf8String(obj.toJSONString(2), reviewPoint);
            zipService.add("reviewPoint.json", reviewPoint);
        }*/

        // 查询投标文件目录
/*        List<BidFileCatalogDto> catalogs = catalogService.listByFileId(fileId);
        if (CollUtil.isNotEmpty(catalogs)) {
            File catalog = new File("temps/catalog.json");
            JSONArray obj = JSONUtil.parseArray(catalogs, JSONConfig.create().setIgnoreNullValue(true));
            FileUtil.writeUtf8String(obj.toJSONString(2), catalog);
            zipService.add("catalogs.json", catalog);
        }*/

        // 项目以及标段信息生成json文件
        AbstractProject projectParam = new AbstractProject();
        projectParam.setId(info.getData().getProjectId());
        Message<AbstractProject> projectDetail = projectClient.projectDetail(projectParam);

        // 设置项目标段
        AbstractProject abstractProject = projectDetail.getData();
        abstractProject.setSections(CollUtil.list(false, info.getData().to(BidSectionDTO.class)));

        // 将项目信息保存到招标文件中
        File projectFile = new File("temps/projectFile.json");
        JSONObject obj = JSONUtil.parseObj(abstractProject,
                JSONConfig.create().setIgnoreNullValue(true));
        FileUtil.writeUtf8String(obj.toJSONString(2), projectFile);
        zipService.add("tradingFileDto.json", projectFile);

        // 查询开标一览表
        Message<List<BidOpeningSchedule>> scheduleMsg = bidOpeningClient.listByFileId(fileId, Integer.valueOf(abstractProject.getProjectType()));
        if (scheduleMsg.isSuccess()) {
            File schedule = new File("temps/schedule.json");
            JSONArray schedules = JSONUtil.parseArray(scheduleMsg.getData(),
                    JSONConfig.create().setIgnoreNullValue(true));
            FileUtil.writeUtf8String(schedules.toJSONString(2), schedule);
            zipService.add("tradingFileScheduleDtos1.json", schedule);
        }

        // 最终的招标文件
        File file = zipService.file(data.getFileName() + ".zbwj");

        // 上传至OSS, 并保存至文件管理中
        UploadEntity uploadEntity = new UploadEntity(file);
        uploadEntity.setBucketName("ddzb-trading");
        List<HbFileInfo> fileInfos = persistenceService.updateToOss("ddzb-trading",
                CannedAccessControlList.PublicRead, new HbMultipartFile(file));

        // 保存至文件管理
        for (HbFileInfo hbFileInfo : fileInfos) {
            hbFileInfo.setDataTable("trade_bid_section");
            hbFileInfo.setDataId(String.valueOf(sectionId));
        }
        persistenceService.record(fileInfos);

        return MsgUtil.success(fileInfos.get(0).getId());
    }
}
